require 'parser/SymTable.rb'
require 'parser/SymFunction.rb'

require 'functions/EyeFunction.rb'
require 'functions/RangeFunction.rb'
require 'functions/ZeroesFunction.rb'

# = Class ASTMain
# Inherits from AST. Represents the implementation of an AST especifically designed
# for the main program structure of the programming language Vectorinox
# == Attributes inherited from AST
# node, children
# == Methods inherited from AST
# check(), run()
class ASTMain < AST
  # List of the declarations of the program's functions
  attr_reader :ldeclfunc
  # Instruction that has to be executed by the program
  attr_reader :inst
  
  # Constructor of the class
  # === Parameters
  # * ldeclfunc: List of the declarations of the program's functions
  # * inst: Instruction that has to be executed by the program
  def initialize ldeclfunc, inst
    @ldeclfunc = ldeclfunc
    @func_table = SymTable.new
    @func_table.insert(EyeFunction.new())
    @func_table.insert(RangeFunction.new())
    @func_table.insert(ZeroesFunction.new())
    if @ldeclfunc != nil
      for func in @ldeclfunc.children
        if nil != @func_table.find(func.name.node.value)
          raise "La función #{func.name.node} está siendo redeclarada"
        end
        @func_table.insert(SymFunction.new(func))
      end
    end
    @inst = inst
  end

  # Method to run the main skeleton of the program
  # === Parameters
  # * parent_sym_table: Symbol table passed by the parent AST
  # * func_table: Function symbol table passed by the parent AST
  # === Return value
  # nil if executed with success or an error message
  def run
    @inst.run SymTable.new(), @func_table
  end
  
  # Method to check the static correctitude of main skeleton of the program
  # === Parameters
  # * parent_sym_table: Symbol table passed by the parent AST
  # * func_table: Function symbol table passed by the pare
  # * func_type: Type of valid return value
  # === Return value
  # nil if executed with success or an error message
  def check
    if @ldeclfunc != nil
      for func in @ldeclfunc.children
        msg = func.check @func_table
        if nil != msg
          return msg
        end
      end
    end
    @inst.check SymTable.new(), @func_table, nil
  end

  # Creates a 'String' representation of the AST with 'i' identation spaces
  # === Parameters
  # * i: Identation with which the AST should be printed with
  def to_s
    ldeclfunc = nil == @ldeclfunc ? "" : "Declaración de funciones: " + @ldeclfunc.to_s(@@c) + "\n"
    "#{ldeclfunc}Instrucciones: #{@inst.to_s(@@c)}\n"
  end
end